﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using G = System.Drawing;
using Win = System.Windows.Forms;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
using S = Microsoft.ClearScript;
using WinS = Microsoft.ClearScript.Windows;

namespace OpenGameKit
{
    public static class Game
    {
        public delegate void GameEventHandler(object sender, GameEventArgs e);
        /// <summary>
        /// Called shortly before the window opens.
        /// </summary>
        public static event GameEventHandler OnStart;
        /// <summary>
        /// Called when it is time to update the game logic.
        /// </summary>
        public static event GameEventHandler OnUpdate;
        /// <summary>
        /// Called when it is time to draw the game again.
        /// </summary>
        public static event GameEventHandler OnRender;
        /// <summary>
        /// Called when the window is about to close and the game has ended.
        /// </summary>
        public static event GameEventHandler OnEnd;

        public static Scene CurrentScene = null;

        internal static GameWindow GmWnd = null;  // GmWnd is short for GameWindow.
        public static int DeltaTime = 1;

        internal static Key KeyHeld = Key.None;
        internal static Key KeyUp = Key.None;
        internal static Key KeyDown = Key.None;
        internal static MouseKey MouseKeyDown = MouseKey.None;
        internal static MouseKey MouseKeyUp = MouseKey.None;

        /// <summary>
        /// Get or set the width of the window, not including the window frame or title bar.
        /// </summary>
        public static int Width
        {
            get
            {
                return GmWnd.ClientSize.Width;
            }
            set
            {
                GmWnd.ClientSize = new G.Size(value, GmWnd.ClientSize.Height);
            }
        }

        /// <summary>
        /// Get or set the height of the window, not including the window frame or title bar.
        /// </summary>
        public static int Height
        {
            get
            {
                return GmWnd.ClientSize.Height;
            }
            set
            {
                GmWnd.ClientSize = new G.Size(value, GmWnd.ClientSize.Height);
            }
        }

        /// <summary>
        /// Allows you to enter fullscreen mode, can only be called once the window has been created.
        /// </summary>
        public static bool Fullscreen
        {
            get
            {
                if (GmWnd.WindowState == WindowState.Fullscreen)
                    return true;
                else
                    return false;
            }
            set
            {
                if (value == true)
                {
                    GmWnd.WindowState = WindowState.Fullscreen;
                    GmWnd.WindowBorder = WindowBorder.Hidden;
                }
                else
                {
                    GmWnd.WindowState = WindowState.Normal;
                    GmWnd.WindowBorder = WindowBorder.Fixed;
                }
            }
        }

        /// <summary>
        /// Get or set the text displayed in the title bar of the window.
        /// </summary>
        public static string Title
        {
            get
            {
                return GmWnd.Title;
            }
            set
            {
                GmWnd.Title = value;
            }
        }

        /// <summary>
        /// Create the window to draw the game on.
        /// </summary>
        /// <param name="width">The width in pixels of the window, not including the frame.</param>
        /// <param name="height">The height in pixels of the window, not including the frame.</param>
        /// <param name="title">The text to display on the title bar of the window.</param>
        public static void CreateWindow(int width, int height, string title)
        {
            if (GmWnd != null)
            {
                GmWnd.Close();
                GmWnd.Dispose();
                GmWnd = null;
            }

            GmWnd = new GameWindow();
            GmWnd.ClientSize = new G.Size(width, height);
            GmWnd.Title = title;
            GmWnd.WindowBorder = WindowBorder.Fixed;

            GmWnd.Load += GmWnd_Load;
            GmWnd.Resize += GmWnd_Resize;
            GmWnd.UpdateFrame += GmWnd_UpdateFrame;
            GmWnd.RenderFrame += GmWnd_RenderFrame;
            GmWnd.Closing += GmWnd_Closing;

            GmWnd.Keyboard.KeyUp += GmWnd_KeyUp;
            GmWnd.Keyboard.KeyDown += GmWnd_KeyDown;
            GmWnd.Mouse.ButtonUp += Mouse_ButtonUp;
            GmWnd.Mouse.ButtonDown += Mouse_ButtonDown;
        }

        public static void Run()
        {
            OnStart += Game_OnStart;
            OnUpdate += Game_OnUpdate;
            OnRender += Game_OnRender;
            OnEnd += Game_OnEnd;

            if (GmWnd != null)
                GmWnd.Run(60, 30);
            else
            {
                // If the window was never created throw an exeption.
                Exception e = new Exception("The run method was called but the window was never created.");
                throw e;
            }
        }

        /// <summary>
        /// Ends the program.
        /// </summary>
        public static void Exit()
        {
            if (GmWnd != null)
                GmWnd.Close();
            Environment.Exit(0);
        }

        /// <summary>
        /// Execute a script file.
        /// </summary>
        /// <param name="file">The JScript file to run.</param>
        /// <param name="sender">The object to set the script Sender variable to.</param>
        public static void RunScript(string file, object sender)
        {
            try
            {
                WinS.JScriptEngine Engine = new WinS.JScriptEngine();
                Engine.AddHostType("Game", typeof(Game));
                Engine.AddHostType("GameMath", typeof(GameMath));
                Engine.AddHostType("Color", typeof(Color));
                Engine.AddHostType("TileSheet", typeof(TileSheet));
                Engine.AddHostType("Sprite", typeof(Sprite));
                Engine.AddHostType("Scene", typeof(Scene));
                Engine.AddHostType("Graphics", typeof(Graphics));

                Engine.AddHostObject("Sender", sender);

                System.IO.StreamReader SR = new System.IO.StreamReader(file);
                Engine.Execute(SR.ReadToEnd());
                Engine.Dispose();
                SR.Dispose();
            }
            catch (Exception)
            {
                Exception e = new Exception("A error was throwen in a script file.");
                throw e;
            }
        }

        private static void GmWnd_Load(object sender, EventArgs e)
        {
            GL.ClearColor(G.Color.Black);

            GL.Enable(EnableCap.Blend);
            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
            OnStart(null, new GameEventArgs());
        }

        private static void GmWnd_Resize(object sender, EventArgs e)
        {
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            GL.Ortho(0, CurrentScene.ViewWidth, CurrentScene.ViewHeight, 0, -1, 1);

            GL.Translate(-CurrentScene.ViewX, -CurrentScene.ViewY, 0);
        }

        private static void GmWnd_UpdateFrame(object sender, FrameEventArgs e)
        {
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            GL.Ortho(0, CurrentScene.ViewWidth, CurrentScene.ViewHeight, 0, -1, 1);

            GL.Translate(-CurrentScene.ViewX, -CurrentScene.ViewY, 0);

            DeltaTime = (int)GmWnd.UpdateTime;

            if (DeltaTime == 0)
                DeltaTime = 1;

            OnUpdate(null, new GameEventArgs());
            CurrentScene.Update();

            MouseKeyUp = MouseKey.None;
            MouseKeyDown = MouseKey.None;
        }

        private static void GmWnd_RenderFrame(object sender, FrameEventArgs e)
        {
            GL.ClearColor(G.Color.FromArgb(CurrentScene.BackColor.A, CurrentScene.BackColor.R, CurrentScene.BackColor.G, 
                CurrentScene.BackColor.B));
            GL.Clear(ClearBufferMask.ColorBufferBit);

            CurrentScene.Render(); // Draw all the needed graphics.
            OnRender(null, new GameEventArgs());

            GmWnd.SwapBuffers();
        }

        private static void GmWnd_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            OnEnd(null, new GameEventArgs());
        }

        private static void Mouse_ButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.Button == MouseButton.Left)
                MouseKeyDown = MouseKey.Left;
            if (e.Button == MouseButton.Right)
                MouseKeyDown = MouseKey.Right;
            if (e.Button == MouseButton.Middle)
                MouseKeyDown = MouseKey.Middle;
        }

        private static void Mouse_ButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (e.Button == MouseButton.Left)
                MouseKeyUp = MouseKey.Left;
            if (e.Button == MouseButton.Right)
                MouseKeyUp = MouseKey.Right;
            if (e.Button == MouseButton.Middle)
                MouseKeyUp = MouseKey.Middle;
        }

        private static void GmWnd_KeyDown(object sender, KeyboardKeyEventArgs e)
        {
            if (e.Key == OpenTK.Input.Key.Q)
            {
                KeyDown = Key.Q;
                KeyHeld = Key.Q;
            }
            if (e.Key == OpenTK.Input.Key.W)
            {
                KeyDown = Key.W;
                KeyHeld = Key.W;
            }
            if (e.Key == OpenTK.Input.Key.E)
            {
                KeyDown = Key.E;
                KeyHeld = Key.E;
            }
            if (e.Key == OpenTK.Input.Key.R)
            {
                KeyDown = Key.R;
                KeyHeld = Key.R;
            }
            if (e.Key == OpenTK.Input.Key.T)
            {
                KeyDown = Key.T;
                KeyHeld = Key.T;
            }
            if (e.Key == OpenTK.Input.Key.Y)
            {
                KeyDown = Key.Y;
                KeyHeld = Key.Y;
            }
            if (e.Key == OpenTK.Input.Key.U)
            {
                KeyDown = Key.U;
                KeyHeld = Key.U;
            }
            if (e.Key == OpenTK.Input.Key.I)
            {
                KeyDown = Key.I;
                KeyHeld = Key.I;
            }
            if (e.Key == OpenTK.Input.Key.O)
            {
                KeyDown = Key.O;
                KeyHeld = Key.O;
            }
            if (e.Key == OpenTK.Input.Key.P)
            {
                KeyDown = Key.P;
                KeyHeld = Key.P;
            }
            if (e.Key == OpenTK.Input.Key.A)
            {
                KeyDown = Key.A;
                KeyHeld = Key.A;
            }
            if (e.Key == OpenTK.Input.Key.S)
            {
                KeyDown = Key.S;
                KeyHeld = Key.S;
            }
            if (e.Key == OpenTK.Input.Key.D)
            {
                KeyDown = Key.D;
                KeyHeld = Key.D;
            }
            if (e.Key == OpenTK.Input.Key.F)
            {
                KeyDown = Key.F;
                KeyHeld = Key.F;
            }
            if (e.Key == OpenTK.Input.Key.G)
            {
                KeyDown = Key.G;
                KeyHeld = Key.G;
            }
            if (e.Key == OpenTK.Input.Key.H)
            {
                KeyDown = Key.H;
                KeyHeld = Key.H;
            }
            if (e.Key == OpenTK.Input.Key.J)
            {
                KeyDown = Key.J;
                KeyHeld = Key.J;
            }
            if (e.Key == OpenTK.Input.Key.K)
            {
                KeyDown = Key.K;
                KeyHeld = Key.K;
            }
            if (e.Key == OpenTK.Input.Key.L)
            {
                KeyDown = Key.L;
                KeyHeld = Key.L;
            }
            if (e.Key == OpenTK.Input.Key.Z)
            {
                KeyDown = Key.Z;
                KeyHeld = Key.Z;
            }
            if (e.Key == OpenTK.Input.Key.X)
            {
                KeyDown = Key.X;
                KeyHeld = Key.X;
            }
            if (e.Key == OpenTK.Input.Key.C)
            {
                KeyDown = Key.C;
                KeyHeld = Key.C;
            }
            if (e.Key == OpenTK.Input.Key.V)
            {
                KeyDown = Key.V;
                KeyHeld = Key.V;
            }
            if (e.Key == OpenTK.Input.Key.B)
            {
                KeyDown = Key.B;
                KeyHeld = Key.B;
            }
            if (e.Key == OpenTK.Input.Key.N)
            {
                KeyDown = Key.N;
                KeyHeld = Key.N;
            }
            if (e.Key == OpenTK.Input.Key.M)
            {
                KeyDown = Key.M;
                KeyHeld = Key.M;
            }
            if (e.Key == OpenTK.Input.Key.Number0)
            {
                KeyDown = Key.Num0;
                KeyHeld = Key.Num0;
            }
            if (e.Key == OpenTK.Input.Key.Number1)
            {
                KeyDown = Key.Num1;
                KeyHeld = Key.Num1;
            }
            if (e.Key == OpenTK.Input.Key.Number2)
            {
                KeyDown = Key.Num2;
                KeyHeld = Key.Num2;
            }
            if (e.Key == OpenTK.Input.Key.Number3)
            {
                KeyDown = Key.Num3;
                KeyHeld = Key.Num3;
            }
            if (e.Key == OpenTK.Input.Key.Number4)
            {
                KeyDown = Key.Num4;
                KeyHeld = Key.Num4;
            }
            if (e.Key == OpenTK.Input.Key.Number5)
            {
                KeyDown = Key.Num5;
                KeyHeld = Key.Num5;
            }
            if (e.Key == OpenTK.Input.Key.Number6)
            {
                KeyDown = Key.Num6;
                KeyHeld = Key.Num6;
            }
            if (e.Key == OpenTK.Input.Key.Number7)
            {
                KeyDown = Key.Num7;
                KeyHeld = Key.Num7;
            }
            if (e.Key == OpenTK.Input.Key.Number8)
            {
                KeyDown = Key.Num8;
                KeyHeld = Key.Num8;
            }
            if (e.Key == OpenTK.Input.Key.Number9)
            {
                KeyDown = Key.Num9;
                KeyHeld = Key.Num9;
            }
            if (e.Key == OpenTK.Input.Key.Escape)
            {
                KeyDown = Key.Escape;
                KeyHeld = Key.Escape;
            }
            if (e.Key == OpenTK.Input.Key.Tilde)
            {
                KeyDown = Key.Tilde;
                KeyHeld = Key.Tilde;
            }
            if (e.Key == OpenTK.Input.Key.Tab)
            {
                KeyDown = Key.Tab;
                KeyHeld = Key.Tab;
            }
            if (e.Key == OpenTK.Input.Key.ShiftLeft)
            {
                KeyDown = Key.Shift;
                KeyHeld = Key.Shift;
            }
            if (e.Key == OpenTK.Input.Key.ShiftRight)
            {
                KeyDown = Key.Shift;
                KeyHeld = Key.Shift;
            }
            if (e.Key == OpenTK.Input.Key.ControlLeft)
            {
                KeyDown = Key.Control;
                KeyHeld = Key.Control;
            }
            if (e.Key == OpenTK.Input.Key.ControlRight)
            {
                KeyDown = Key.Control;
                KeyHeld = Key.Control;
            }
            if (e.Key == OpenTK.Input.Key.AltLeft)
            {
                KeyDown = Key.Alt;
                KeyHeld = Key.Alt;
            }
            if (e.Key == OpenTK.Input.Key.Enter)
            {
                KeyDown = Key.Return;
                KeyHeld = Key.Return;
            }
            if (e.Key == OpenTK.Input.Key.Comma)
            {
                KeyDown = Key.Comma;
                KeyHeld = Key.Comma;
            }
            if (e.Key == OpenTK.Input.Key.Period)
            {
                KeyDown = Key.Period;
                KeyHeld = Key.Period;
            }
            if (e.Key == OpenTK.Input.Key.Slash)
            {
                KeyDown = Key.Slash;
                KeyHeld = Key.Slash;
            }
            if (e.Key == OpenTK.Input.Key.Semicolon)
            {
                KeyDown = Key.SemiColon;
                KeyHeld = Key.SemiColon;
            }
            if (e.Key == OpenTK.Input.Key.Quote)
            {
                KeyDown = Key.Quote;
                KeyHeld = Key.Quote;
            }
            if (e.Key == OpenTK.Input.Key.BracketLeft)
            {
                KeyDown = Key.BracketOpen;
                KeyHeld = Key.BracketOpen;
            }
            if (e.Key == OpenTK.Input.Key.BracketRight)
            {
                KeyDown = Key.BracketClose;
                KeyHeld = Key.BracketClose;
            }
            if (e.Key == OpenTK.Input.Key.BackSlash)
            {
                KeyDown = Key.BackSlash;
                KeyHeld = Key.BackSlash;
            }
            if (e.Key == OpenTK.Input.Key.BackSpace)
            {
                KeyDown = Key.Backspace;
                KeyHeld = Key.Backspace;
            }
            if (e.Key == OpenTK.Input.Key.Plus)
            {
                KeyDown = Key.Add;
                KeyHeld = Key.Add;
            }
            if (e.Key == OpenTK.Input.Key.Minus)
            {
                KeyDown = Key.Subtract;
                KeyHeld = Key.Subtract;
            }
            if (e.Key == OpenTK.Input.Key.Space)
            {
                KeyDown = Key.Space;
                KeyHeld = Key.Space;
            }
            if (e.Key == OpenTK.Input.Key.Up)
            {
                KeyDown = Key.Up;
                KeyHeld = Key.Up;
            }
            if (e.Key == OpenTK.Input.Key.Down)
            {
                KeyDown = Key.Down;
                KeyHeld = Key.Down;
            }
            if (e.Key == OpenTK.Input.Key.Left)
            {
                KeyDown = Key.Left;
                KeyHeld = Key.Right;
            }
        }

        private static void GmWnd_KeyUp(object sender, KeyboardKeyEventArgs e)
        {
            KeyHeld = Key.None;

            if (e.Key == OpenTK.Input.Key.Q)
                KeyUp = Key.Q;
            if (e.Key == OpenTK.Input.Key.W)
                KeyUp = Key.W;
            if (e.Key == OpenTK.Input.Key.E)
                KeyUp = Key.E;
            if (e.Key == OpenTK.Input.Key.R)
                KeyUp = Key.R;
            if (e.Key == OpenTK.Input.Key.T)
                KeyUp = Key.T;
            if (e.Key == OpenTK.Input.Key.Y)
                KeyUp = Key.Y;
            if (e.Key == OpenTK.Input.Key.U)
                KeyUp = Key.U;
            if (e.Key == OpenTK.Input.Key.I)
                KeyUp = Key.I;
            if (e.Key == OpenTK.Input.Key.O)
                KeyUp = Key.O;
            if (e.Key == OpenTK.Input.Key.P)
                KeyUp = Key.P;
            if (e.Key == OpenTK.Input.Key.A)
                KeyUp = Key.A;
            if (e.Key == OpenTK.Input.Key.S)
                KeyUp = Key.S;
            if (e.Key == OpenTK.Input.Key.D)
                KeyUp = Key.D;
            if (e.Key == OpenTK.Input.Key.F)
                KeyUp = Key.F;
            if (e.Key == OpenTK.Input.Key.G)
                KeyUp = Key.G;
            if (e.Key == OpenTK.Input.Key.H)
                KeyUp = Key.H;
            if (e.Key == OpenTK.Input.Key.J)
                KeyUp = Key.J;
            if (e.Key == OpenTK.Input.Key.K)
                KeyUp = Key.K;
            if (e.Key == OpenTK.Input.Key.L)
                KeyUp = Key.L;
            if (e.Key == OpenTK.Input.Key.Z)
                KeyUp = Key.Z;
            if (e.Key == OpenTK.Input.Key.X)
                KeyUp = Key.X;
            if (e.Key == OpenTK.Input.Key.C)
                KeyUp = Key.C;
            if (e.Key == OpenTK.Input.Key.V)
                KeyUp = Key.V;
            if (e.Key == OpenTK.Input.Key.B)
                KeyUp = Key.B;
            if (e.Key == OpenTK.Input.Key.N)
                KeyUp = Key.N;
            if (e.Key == OpenTK.Input.Key.M)
                KeyUp = Key.M;
            if (e.Key == OpenTK.Input.Key.Number0)
                KeyUp = Key.Num0;
            if (e.Key == OpenTK.Input.Key.Number1)
                KeyUp = Key.Num1;
            if (e.Key == OpenTK.Input.Key.Number2)
                KeyUp = Key.Num2;
            if (e.Key == OpenTK.Input.Key.Number3)
                KeyUp = Key.Num3;
            if (e.Key == OpenTK.Input.Key.Number4)
                KeyUp = Key.Num4;
            if (e.Key == OpenTK.Input.Key.Number5)
                KeyUp = Key.Num5;
            if (e.Key == OpenTK.Input.Key.Number6)
                KeyUp = Key.Num6;
            if (e.Key == OpenTK.Input.Key.Number7)
                KeyUp = Key.Num7;
            if (e.Key == OpenTK.Input.Key.Number8)
                KeyUp = Key.Num8;
            if (e.Key == OpenTK.Input.Key.Number9)
                KeyUp = Key.Num9;
            if (e.Key == OpenTK.Input.Key.Escape)
                KeyUp = Key.Escape;
            if (e.Key == OpenTK.Input.Key.Tilde)
                KeyUp = Key.Tilde;
            if (e.Key == OpenTK.Input.Key.Tab)
                KeyUp = Key.Tab;
            if (e.Key == OpenTK.Input.Key.ShiftLeft)
                KeyUp = Key.Shift;
            if (e.Key == OpenTK.Input.Key.ShiftRight)
                KeyUp = Key.Shift;
            if (e.Key == OpenTK.Input.Key.ControlLeft)
                KeyUp = Key.Control;
            if (e.Key == OpenTK.Input.Key.ControlRight)
                KeyUp = Key.Control;
            if (e.Key == OpenTK.Input.Key.AltLeft)
                KeyUp = Key.Alt;
            if (e.Key == OpenTK.Input.Key.AltRight)
                KeyUp = Key.Alt;
            if (e.Key == OpenTK.Input.Key.Enter)
                KeyUp = Key.Return;
            if (e.Key == OpenTK.Input.Key.Comma)
                KeyUp = Key.Comma;
            if (e.Key == OpenTK.Input.Key.Period)
                KeyUp = Key.Period;
            if (e.Key == OpenTK.Input.Key.Slash)
                KeyUp = Key.Slash;
            if (e.Key == OpenTK.Input.Key.Semicolon)
                KeyUp = Key.SemiColon;
            if (e.Key == OpenTK.Input.Key.Quote)
                KeyUp = Key.Quote;
            if (e.Key == OpenTK.Input.Key.BracketLeft)
                KeyUp = Key.BracketOpen;
            if (e.Key == OpenTK.Input.Key.BracketRight)
                KeyUp = Key.BracketClose;
            if (e.Key == OpenTK.Input.Key.BackSlash)
                KeyUp = Key.BackSlash;
            if (e.Key == OpenTK.Input.Key.BackSpace)
                KeyUp = Key.Backspace;
            if (e.Key == OpenTK.Input.Key.Plus)
                KeyUp = Key.Add;
            if (e.Key == OpenTK.Input.Key.Minus)
                KeyUp = Key.Subtract;
            if (e.Key == OpenTK.Input.Key.Space)
                KeyUp = Key.Space;
            if (e.Key == OpenTK.Input.Key.Up)
                KeyUp = Key.Up;
            if (e.Key == OpenTK.Input.Key.Down)
                KeyUp = Key.Down;
            if (e.Key == OpenTK.Input.Key.Left)
                KeyUp = Key.Left;
            if (e.Key == OpenTK.Input.Key.Right)
                KeyUp = Key.Right;
        }

        #region GAME ENGINE EVENTS

        private static void Game_OnStart(object sender, GameEventArgs e)
        {
        }

        private static void Game_OnRender(object sender, GameEventArgs e)
        {
        }

        private static void Game_OnUpdate(object sender, GameEventArgs e)
        {
        }

        private static void Game_OnEnd(object sender, GameEventArgs e)
        {
        }

        #endregion

        #region INPUT

        public static Key GetKey()
        {
            return KeyHeld;
        }

        public static Key GetKeyDown()
        {
            return KeyDown;
        }

        public static Key GetKeyUp()
        {
            return KeyUp;
        }

        public static int GetMouseX()
        {
            return GmWnd.Mouse.X;
        }

        public static int GetMouseY()
        {
            return GmWnd.Mouse.Y;
        }

        public static MouseKey GetMouseDown()
        {
            return MouseKeyDown;
        }

        public static MouseKey GetMouseUp()
        {
            return MouseKeyUp;
        }

        public enum MouseKey
        {
            Left,
            Right,
            Middle,
            None,
        }

        public enum Key
        {
            Q,
            W,
            E,
            R,
            T,
            Y,
            U,
            I,
            O,
            P,
            A,
            S,
            D,
            F,
            G,
            H,
            J,
            K,
            L,
            Z,
            X,
            C,
            V,
            B,
            N,
            M,
            Num1,
            Num2,
            Num3,
            Num4,
            Num5,
            Num6,
            Num7,
            Num8,
            Num9,
            Num0,
            Escape,
            Tilde,
            Tab,
            Shift,
            Control,
            Alt,
            Return,
            Comma,
            Period,
            Slash,
            SemiColon,
            Quote,
            BracketOpen,
            BracketClose,
            BackSlash,
            Backspace,
            Add,
            Subtract,
            Space,
            None,
            Up,
            Down,
            Left,
            Right
        }

        #endregion
    }
}
